#ifndef __WIZ_BNF_ACTOR_HPP__SHANHAOBO_19800429__
#define __WIZ_BNF_ACTOR_HPP__SHANHAOBO_19800429__

#include "../../Base/WizBase.hpp"
#include "../../DataType/Tuple/WizDataTypeTuple.hpp"

#include "./WizBNFActorComposite.hpp"

#include "./WizBNFActorOperators.hpp"

namespace Wiz
{
    namespace BNF
    {
        namespace Actor
        {
            //////////////////////////////////
            template <typename TupleT>
            struct UnpackTuple : public TupleT
            {
                typedef TupleT              tTuple;
                typedef TupleT              tSuper;

                UnpackTuple()
                {}
                UnpackTuple(tTuple const &Tpl) : tSuper(Tpl)
                {}
            }; /// end of struct UnpackTuple
            //////////////////////////////////

            namespace Value
            {
                template <typename T>
                struct Type
                {
                    typedef typename ::Wiz::TypeTraits::Remove::Reference<T>::tType     tPlain;

                    template <typename TupleT>
                    struct Result
                    {
                        typedef tPlain const                                            tType;
                    };

                    Type(tPlain Val) : m_Value(Val)
                    {}

                    template <typename TupleT>
                    tPlain const
                    Evaluate(TupleT const& ) const
                    {
                        return m_Value;
                    }

                    tPlain m_Value;
                };
            } /// end of namespace Value

            //////////////////////////////////
            template <typename BaseT>
            struct Type : public BaseT
            {
                typedef BaseT           tSuper;
                typedef Type            tThis;

                Type() : tSuper()
                {
                }
                Type(tSuper const& Bs) : tSuper(Bs)
                {
                }

                typename ::Wiz::BNF::Actor::Result<BaseT, ::Wiz::Tuple::Type<>>::tType
                    operator()() const
                {
                    return tSuper::Evaluate(::Wiz::Tuple::Type<>());
                }

                template <typename T0>
                typename ::Wiz::BNF::Actor::Result<BaseT, ::Wiz::Tuple::Type<T0&>>::tType
                    operator()(T0& a) const
                {
                    return tSuper::Evaluate(::Wiz::Tuple::Type<T0&>(a));
                }

                template <typename T0, typename T1>
                typename ::Wiz::BNF::Actor::Result<BaseT, ::Wiz::Tuple::Type<T0&, T1&>>::tType
                    operator()(T0& a, T1& b) const
                {
                    return tSuper::Evaluate(::Wiz::Tuple::Type<T0&, T1&>(a, b));
                }

                template <typename T0, typename T1, typename T2>
                typename ::Wiz::BNF::Actor::Result<BaseT, ::Wiz::Tuple::Type<T0&, T1&, T2&>>::tType
                    operator()(T0& a, T1& b, T2& c) const
                {
                    return tSuper::Evaluate(::Wiz::Tuple::Type<T0&, T1&, T2&>(a, b, c));
                }

                template <typename T0, typename T1, typename T2, typename T3>
                typename ::Wiz::BNF::Actor::Result<BaseT, ::Wiz::Tuple::Type<T0&, T1&, T2&, T3&> >::tType
                    operator()(T0& a, T1& b, T2& c, T3& d) const
                {
                    return tSuper::Evaluate(::Wiz::Tuple::Type<T0&, T1&, T2&, T3&>(a, b, c, d));
                }

                template <typename T0, typename T1, typename T2, typename T3, typename T4>
                typename ::Wiz::BNF::Actor::Result<BaseT, ::Wiz::Tuple::Type<T0&, T1&, T2&, T3&, T4&> >::tType
                    operator()(T0& a, T1& b, T2& c, T3& d, T4& e) const
                {
                    return tSuper::Evaluate(::Wiz::Tuple::Type<T0&, T1&, T2&, T3&, T4&>(a, b, c, d, e));
                }

                template <typename T0, typename T1, typename T2, typename T3, typename T4, typename T5>
                typename ::Wiz::BNF::Actor::Result<BaseT, ::Wiz::Tuple::Type<T0&, T1&, T2&, T3&, T4&, T5&> >::tType
                    operator()(T0& a, T1& b, T2& c, T3& d, T4& e, T5& f) const
                {
                    return tSuper::Evaluate(::Wiz::Tuple::Type<T0&, T1&, T2&, T3&, T4&, T5&>(a, b, c, d, e, f));
                }

                template <typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
                typename ::Wiz::BNF::Actor::Result<BaseT, ::Wiz::Tuple::Type<T0&, T1&, T2&, T3&, T4&, T5&, T6&>>::tType
                    operator()(T0& a, T1& b, T2& c, T3& d, T4& e, T5& f, T6& g) const
                {
                    return tSuper::Evaluate(::Wiz::Tuple::Type<T0&, T1&, T2&, T3&, T4&, T5&, T6&>(a, b, c, d, e, f, g));
                }

                template <typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7>
                typename ::Wiz::BNF::Actor::Result<BaseT, ::Wiz::Tuple::Type<T0&, T1&, T2&, T3&, T4&, T5&, T6&, T7&>>::tType
                    operator()(T0& a, T1& b, T2& c, T3& d, T4& e, T5& f, T6& g, T7& h) const
                {
                    return tSuper::Evaluate(::Wiz::Tuple::Type<T0&, T1&, T2&, T3&, T4&, T5&, T6&, T7&>(a, b, c, d, e, f, g, h));
                }

                template <typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8>
                typename ::Wiz::BNF::Actor::Result<BaseT, ::Wiz::Tuple::Type<T0&, T1&, T2&, T3&, T4&, T5&, T6&, T7&, T8&>>::tType
                    operator()(T0& a, T1& b, T2& c, T3& d, T4& e, T5& f, T6& g, T7& h, T8& i) const
                {
                    return tSuper::Evaluate(::Wiz::Tuple::Type<T0&, T1&, T2&, T3&, T4&, T5&, T6&, T7&, T8&>(a, b, c, d, e, f, g, h, i));
                }

                template <typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9>
                typename ::Wiz::BNF::Actor::Result<BaseT, ::Wiz::Tuple::Type<T0&, T1&, T2&, T3&, T4&, T5&, T6&, T7&, T8&, T9&>>::tType
                    operator()(T0& a, T1& b, T2& c, T3& d, T4& e, T5& f, T6& g, T7& h, T8& i, T9& j) const
                {
                    return tSuper::Evaluate(::Wiz::Tuple::Type<T0&, T1&, T2&, T3&, T4&, T5&, T6&, T7&, T8&, T9&>(a, b, c, d, e, f, g, h, i, j));
                }

                template <typename TupleT>
                typename ::Wiz::BNF::Actor::Result<BaseT, UnpackTuple<TupleT>>::tType
                    operator()(UnpackTuple<TupleT> const &t) const
                {
                    return tSuper::Evaluate(t);
                }

                /// Binary
                template <typename ElementT>
                typename ::Wiz::BNF::Composite::MakeBinary1<::Wiz::BNF::Actor::Operators::Binary::Assign, BaseT, ElementT>::tType
                    operator=(ElementT const& Arg1) const
                {
                    return ::Wiz::BNF::Composite::MakeBinary1<::Wiz::BNF::Actor::Operators::Binary::Assign, BaseT, ElementT>::Construct(*this, Arg1);
                }

                template <typename ElementT>
                typename ::Wiz::BNF::Composite::MakeBinary1<::Wiz::BNF::Actor::Operators::Binary::Index, BaseT, ElementT>::tType
                    operator[](ElementT const& Arg1) const
                {
                    return ::Wiz::BNF::Composite::MakeBinary1<::Wiz::BNF::Actor::Operators::Binary::Index, BaseT, ElementT>::Construct(*this, Arg1);
                }
            };
            ////////////////////////////////////////////////////////////////////////////////////////////////////

            ///////////////////////////////////
            template <typename T>
            struct As
            {
                typedef ::Wiz::BNF::Actor::Type<::Wiz::BNF::Actor::Value::Type<T>>           tType;
                static tType Convert(T const& X)
                {
                    return ::Wiz::BNF::Actor::Value::Type<T>(X);
                }
            };
            template <typename T, ::Wiz::Int::Type N>
            struct As<T[N]>
            {
                typedef ::Wiz::BNF::Actor::Type<::Wiz::BNF::Actor::Value::Type<T const*>>    tType;
                static tType Convert(T const X[N])
                {
                    return ::Wiz::BNF::Actor::Value::Type<T const*>(X);
                }
            };

            /////////////////////////////////
            template <typename BaseT>
            struct As<::Wiz::BNF::Actor::Type<BaseT>>
            {
                typedef ::Wiz::BNF::Actor::Type<BaseT> tType;

                static tType Convert(::Wiz::BNF::Actor::Type<BaseT> const& x)
                {
                    return x;
                }
            };

            //////////////////////////////////
            template <>
            struct As<::Wiz::Null::Type>
            {

                typedef ::Wiz::Null::Type tType;
                static ::Wiz::Null::Type Convert(::Wiz::Null::Type)
                {
                    return ::Wiz::Null::Type();
                }
            };

            //////////////////////////////////
            template <>
            struct As<::Wiz::Void::Type> {
                typedef ::Wiz::Void::Type tType;
                //  ERROR!!!
            };
            ///////////////////////////////////
        } /// end of namespace Actor
    } /// end of namespace 
} /// end of namespace Wiz

#endif /*__WIZ_BNF_ACTOR_HPP__SHANHAOBO_19800429__*/
